package com.tom.redis.train;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;

/**
 * redis实战书第二章代码练习
 *
 * @author yanghongjun19
 * @date 2020/12/20 20:04
 **/
public class Chapter02 {

    public static Jedis jedis;

    public static void main(String[] args) {
        jedis = new Jedis("127.0.0.1", 7000);

        //1:设置token
        for (int i = 0; i < 10000; i++) {
            String token = UUID.randomUUID().toString();
            updateToken(token, "user:id:" + i, "iphone" + i);

            //2:获取用户信息
            System.out.println("用户信息是->" + checkToken(token));
        }

        //3:清理多余的数据(限制只能保存1000个用户信息)
        CleanSessionsThead thread = new CleanSessionsThead(jedis, 1200);
        try {
            thread.start();
            Thread.sleep(3000);
            thread.quit();
            Thread.sleep(2000);
            if (thread.isAlive()) {
                throw new RuntimeException("The clean sessions thread is still alive?!?");
            } else {
                System.out.println("正常结束");
            }


        } catch (Exception e) {

        }

    }

    public static void updateToken(String token, String user, String goods) {
        long timestamp = System.currentTimeMillis() / 1000;
        Transaction multi = jedis.multi();
        //1:设置用户token及保存token有序集合
        multi.hset("login:", token, user);
        multi.zadd("recent:", timestamp, token);

        //2:设置用户浏览了商品
        if (goods != null) {
            multi.zadd("viewed:" + token, timestamp, goods);
            //3:最多保留25个商品(把旧的数据删除)
            multi.zremrangeByRank("viewed:" + token, 0, -26);
        }

        multi.exec();
    }

    public static String checkToken(String token) {
        return jedis.hget("login:", token);
    }


    public static class CleanSessionsThead extends Thread {

        private Jedis jedis;
        private int limit;
        private boolean quit;

        public CleanSessionsThead(Jedis jedis, int limit) {
            this.jedis = jedis;
            this.limit = limit;
        }

        public void quit() {
            quit = true;
        }


        @Override
        public void run() {
            while (!quit) {
                Long size = jedis.zcard("recent:");
                if (size <= limit) {
                    try {
                        sleep(1000);
                        continue;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                long endIndex = Math.min(100, size - limit);

                Set<String> sessionSet = jedis.zrange("recent:", 0, endIndex - 1);
                String[] sessions = sessionSet.toArray(new String[sessionSet.size()]);

                ArrayList<String> sessionKeys = new ArrayList<String>();
                for (String sess : sessions) {
                    sessionKeys.add("viewed:" + sess);
                }

                Transaction multi = jedis.multi();
                multi.del(sessionKeys.toArray(new String[sessionKeys.size()]));
                multi.zrem("recent:", sessions);
                multi.hdel("login:", sessions);
                multi.exec();
            }
        }
    }
}
